home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lfslib / fileAccess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-17  |  34.7 KB  |  1,210 lines

  1. /* 
  2.  * fileAccess.c --
  3.  *
  4.  *    Routines for access LFS files from user level using
  5.  *    the raw disk interface. These routines are intended 
  6.  *    to be called by crash recovery and other user programs
  7.  *    that needed to scan the file.
  8.  *
  9.  * Copyright 1990 Regents of the University of California
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.3 90/01/12 12:03:36 douglis Exp $ SPRITE (Berkeley)";
  21. #endif /* not lint */
  22.  
  23. #include "lfslib.h"
  24. #include "lfslibInt.h"
  25. #include <varargs.h>
  26. #include <sys/types.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <alloca.h>
  30. #include <bstring.h>
  31. #include <string.h>
  32.  
  33. enum AccessFileOp { OP_GET, OP_SET};
  34.  
  35. static Boolean AccessFileBlockAddr _ARGS_((enum AccessFileOp op, 
  36.     LfsFile *filePtr, int blockNum, int *blockaddrPtr, int *blocksizePtr));
  37.  
  38. static LfsFile    *GetDirtyFile _ARGS_((Lfs *lfsPtr));
  39. static void ReturnDirtyFile _ARGS_((LfsFile *filePtr, Boolean onFront));
  40. static LfsFileBlock *GetDirtyBlock _ARGS_((LfsFile *filePtr, int blockType, 
  41.             int *lastDirtyBlockPtr));
  42. static void ReturnDirtyBlock _ARGS_((LfsFileBlock *fileBlockPtr,
  43.             Boolean written));
  44.  
  45.  
  46. /*
  47.  *----------------------------------------------------------------------
  48.  *
  49.  * LfsFileOpenDesc --
  50.  *
  51.  *    Open a file specified by the LfsDescriptor for access.
  52.  *
  53.  * Results:
  54.  *    SUCCESS if file can be access. 
  55.  *
  56.  * Side effects:
  57.  *    None.
  58.  *
  59.  *----------------------------------------------------------------------
  60.  */
  61. ReturnStatus
  62. LfsFileOpenDesc(lfsPtr, descPtr, filePtrPtr)
  63.     Lfs    *lfsPtr;    /*  File system of file. */
  64.     LfsFileDescriptor    *descPtr; /* Descriptor of file we want. */
  65.     LfsFile **filePtrPtr;    /* OUT: Filled in File structure. */
  66. {
  67.     LfsFile        *filePtr;
  68.     int    fileNumber;    
  69.  
  70.     fileNumber = descPtr->fileNumber;
  71.     /*
  72.      * First we lookup the entry in the cache of recently accessed
  73.      * and/or modified files.
  74.      */
  75.     filePtr = (LfsFile *) NULL; /* Quiet down SaberC lint. */
  76.     LIST_FORALL(&lfsPtr->fileLayout.activeFileListHdr, (List_Links *) filePtr) { 
  77.     if ((filePtr->desc.fileNumber == fileNumber) &&
  78.         (bcmp((char *) descPtr, (char *) &(filePtr->desc), 
  79.          sizeof(LfsFileDescriptor)) == 0)) {
  80.         (*filePtrPtr) = filePtr;
  81.         return SUCCESS;
  82.     }
  83.     }
  84.  
  85.     filePtr = (LfsFile *) malloc(sizeof(LfsFile));
  86.     List_InitElement((List_Links *) filePtr);
  87.     List_Insert((List_Links *) filePtr, 
  88.         LIST_ATFRONT(&lfsPtr->fileLayout.activeFileListHdr));
  89.     filePtr->lfsPtr = lfsPtr;
  90.     filePtr->desc = *descPtr;
  91.     List_Init(&filePtr->blockListHdr);
  92.     filePtr->descModified = FALSE;
  93.     (*filePtrPtr) = filePtr;
  94.     return SUCCESS;
  95. }
  96.  
  97. /*
  98.  *----------------------------------------------------------------------
  99.  *
  100.  * LfsFileOpen --
  101.  *
  102.  *    Open a file (specifed by fileNumber) for access.
  103.  *
  104.  * Results:
  105.  *    SUCCESS if file can be access. FS_FILE_NOT_FOUND if we can't
  106.  *    file the file.
  107.  *
  108.  * Side effects:
  109.  *    None.
  110.  *
  111.  *----------------------------------------------------------------------
  112.  */
  113. ReturnStatus
  114. LfsFileOpen(lfsPtr, fileNumber, filePtrPtr)
  115.     Lfs    *lfsPtr;    /*  File system of file. */
  116.     int    fileNumber;    /* File we are looking for. */
  117.     LfsFile **filePtrPtr;    /* OUT: Filled in File structure. */
  118. {
  119.     LfsDescMapEntry    *descMapEntryPtr;
  120.     LfsFileDescriptor    *descPtr;
  121.     int            bufSize, j;
  122.     char        *descBuf;
  123.     LfsFile        *filePtr;
  124.  
  125.     /*
  126.      * First we lookup the entry in the cache of recently accessed
  127.      * and/or modified files.
  128.      */
  129.     filePtr = (LfsFile *) NULL; /* Quiet down SaberC lint. */
  130.     LIST_FORALL(&lfsPtr->fileLayout.activeFileListHdr, 
  131.             (List_Links *) filePtr) { 
  132.     if ((filePtr->desc.fileNumber == fileNumber)) {
  133.         (*filePtrPtr) = filePtr;
  134.         return SUCCESS;
  135.     }
  136.     }
  137.     descMapEntryPtr = LfsGetDescMapEntry(lfsPtr, fileNumber);
  138.     if ((descMapEntryPtr == (LfsDescMapEntry *) NIL) ||
  139.         !(descMapEntryPtr->flags & LFS_DESC_MAP_ALLOCED)) {
  140.     return FS_FILE_NOT_FOUND;
  141.     }
  142.  
  143.     bufSize = lfsPtr->superBlock.fileLayout.descPerBlock * sizeof(*descPtr);
  144.     descBuf = alloca(bufSize);
  145.     if (LfsDiskRead(lfsPtr, descMapEntryPtr->blockAddress, bufSize, descBuf)
  146.         != bufSize) {
  147.     return FS_FILE_NOT_FOUND;
  148.     }
  149.     descPtr = (LfsFileDescriptor *)descBuf;
  150.     for (j = 0; j < lfsPtr->superBlock.fileLayout.descPerBlock; j++) {
  151.     if (descPtr->common.magic != FSDM_FD_MAGIC){
  152.         break;
  153.     }
  154.     if (descPtr->fileNumber == fileNumber) {
  155.         break;
  156.     }
  157.     descPtr++;
  158.     }
  159.     if ((j >= lfsPtr->superBlock.fileLayout.descPerBlock) ||
  160.     !(descPtr->common.flags & FSDM_FD_ALLOC) ||
  161.     (descPtr->fileNumber != fileNumber)) {
  162.     return FS_FILE_NOT_FOUND;
  163.     }
  164.     return LfsFileOpenDesc(lfsPtr, descPtr, filePtrPtr);
  165. }
  166.  
  167. /*
  168.  *----------------------------------------------------------------------
  169.  *
  170.  * LfsFileClose --
  171.  *
  172.  *    Close a previously allocated File.  This routine free resources
  173.  *    allocated by a File routine.
  174.  *
  175.  * Results:
  176.  *    None.
  177.  *
  178.  * Side effects:
  179.  *    None.
  180.  *
  181.  *----------------------------------------------------------------------
  182.  */
  183.  
  184. void
  185. LfsFileClose(filePtr)
  186.     LfsFile    *filePtr;    /* File to close. */
  187. {
  188.     LfsFileBlock    *fileBlockPtr;
  189.     List_Links    *nextPtr;
  190.     int        dirtyBlocks;
  191.  
  192.     /*
  193.      * Free up all nondirty blocks fetched.
  194.      */
  195.     dirtyBlocks = 0;
  196.     fileBlockPtr = (LfsFileBlock *) List_First(&filePtr->blockListHdr);
  197.     while (!List_IsAtEnd(&filePtr->blockListHdr, (List_Links *) fileBlockPtr)) {
  198.     nextPtr = List_Next((List_Links *) fileBlockPtr);
  199.     if (fileBlockPtr->modified) {
  200.         dirtyBlocks++;
  201.     } else {
  202.         List_Remove((List_Links *) fileBlockPtr);
  203.         free((char *) fileBlockPtr);
  204.     }
  205.     fileBlockPtr = (LfsFileBlock *) nextPtr;
  206.     }
  207.     /*
  208.      * Free up the File data structure if nothing is dirty on the file.
  209.      */
  210.     if (filePtr->descModified || dirtyBlocks) {
  211.     return;
  212.     }
  213.     List_Remove((List_Links *) filePtr);
  214.     free((char *) filePtr);
  215. }
  216.  
  217. /*
  218.  *----------------------------------------------------------------------
  219.  *
  220.  * LfsFileBlockFetch --
  221.  *
  222.  *    Fetch a specified block of a File.
  223.  *
  224.  * Results:
  225.  *    ReturnStatus.
  226.  *
  227.  * Side effects:
  228.  *    None.
  229.  *
  230.  *----------------------------------------------------------------------
  231.  */
  232.  
  233. ReturnStatus
  234. LfsFileBlockFetch(filePtr, blockNum, fileBlockPtrPtr)
  235.     LfsFile    *filePtr;    /* File to fetch block from. */
  236.     int        blockNum;    /* Block number to fetch. */
  237.     LfsFileBlock    **fileBlockPtrPtr;  /* OUT: Allocated file block. */
  238.  
  239. {
  240.     LfsFileBlock    *fileBlockPtr;
  241.     int blockAddr, blocksize;
  242.  
  243.     /*
  244.      * First check to see if we already have the block to this file 
  245.      * in our list.
  246.      */
  247.     fileBlockPtr = (LfsFileBlock *) NULL;
  248.     LIST_FORALL(&filePtr->blockListHdr, (List_Links *) fileBlockPtr) {
  249.     if (fileBlockPtr->blockNum == blockNum) {
  250.         (*fileBlockPtrPtr) = fileBlockPtr;
  251.         return SUCCESS;
  252.     }
  253.     }
  254.     /*
  255.      * Fetch the block from disk.
  256.      */
  257.     blockAddr = LfsFileBlockAddr(filePtr, blockNum, &blocksize);
  258.     if (blockAddr == FSDM_NIL_INDEX) {
  259.     return FS_FILE_NOT_FOUND;
  260.     }
  261.     fileBlockPtr = (LfsFileBlock *) malloc(sizeof(LfsFileBlock));
  262.     List_InitElement((List_Links *) fileBlockPtr);
  263.     fileBlockPtr->filePtr = filePtr;
  264.     fileBlockPtr->blockNum = blockNum;
  265.     fileBlockPtr->blockSize = blocksize;
  266.     fileBlockPtr->blockAddr = blockAddr;
  267.     fileBlockPtr->modified = FALSE;
  268.     if (LfsDiskRead(filePtr->lfsPtr, blockAddr, blocksize, 
  269.         fileBlockPtr->contents) != blocksize) {
  270.     free((char *) fileBlockPtr);
  271.     return DEV_HARD_ERROR;
  272.     }
  273.     List_Insert((List_Links *) fileBlockPtr, 
  274.         LIST_ATREAR(&filePtr->blockListHdr));
  275.     (*fileBlockPtrPtr) = fileBlockPtr;
  276.     return SUCCESS;
  277. }
  278.  
  279. /*
  280.  *----------------------------------------------------------------------
  281.  *
  282.  * LfsFileBlockAlloc --
  283.  *
  284.  *    Allocate a new block to a file. The block is the specified size.
  285.  *    The caller is responsible for initializing the new block.
  286.  *
  287.  * Results:
  288.  *    SUCCESS
  289.  *
  290.  * Side effects:
  291.  *    None.
  292.  *
  293.  *----------------------------------------------------------------------
  294.  */
  295.  
  296. ReturnStatus
  297. LfsFileBlockAlloc(filePtr,blockNum, blocksize, fileBlockPtrPtr)
  298.     LfsFile    *filePtr; /* File to allocate block for. */
  299.     int        blockNum; /* Block number of allocate. */
  300.     int        blocksize; /* Size in bytes of new block. */
  301.     LfsFileBlock    **fileBlockPtrPtr; /* OUT: New allocated file block. */
  302. {
  303.     LfsFileBlock    *fileBlockPtr;
  304.  
  305.     /*
  306.      * First check to see if we already have the block to this file 
  307.      * in our list.
  308.      */
  309.     fileBlockPtr = (LfsFileBlock *) NULL;
  310.     LIST_FORALL(&filePtr->blockListHdr, (List_Links *) fileBlockPtr) {
  311.     if (fileBlockPtr->blockNum == blockNum) {
  312.         (*fileBlockPtrPtr) = fileBlockPtr;
  313.         return SUCCESS;
  314.     }
  315.     }
  316.     /*
  317.      * Allocate and returned the block.
  318.      */
  319.     fileBlockPtr = (LfsFileBlock *) malloc(sizeof(LfsFileBlock));
  320.     bzero((char *) fileBlockPtr, sizeof(LfsFileBlock));
  321.     List_InitElement((List_Links *) fileBlockPtr);
  322.     fileBlockPtr->filePtr = filePtr;
  323.     fileBlockPtr->blockNum = blockNum;
  324.     fileBlockPtr->blockSize = blocksize;
  325.     fileBlockPtr->blockAddr = FSDM_NIL_INDEX;
  326.     fileBlockPtr->modified = TRUE;
  327.     List_Insert((List_Links *) fileBlockPtr, 
  328.         LIST_ATREAR(&filePtr->blockListHdr));
  329.     (*fileBlockPtrPtr) = fileBlockPtr;
  330.     return SUCCESS;
  331. }
  332.  
  333. /*
  334.  *----------------------------------------------------------------------
  335.  *
  336.  * LfsFileBlockAddr --
  337.  *
  338.  *    Return the address of a file block.
  339.  *
  340.  * Results:
  341.  *    Address of block. FSDM_NIL_INDEX if block is not found.
  342.  *
  343.  * Side effects:
  344.  *    None.
  345.  *
  346.  *----------------------------------------------------------------------
  347.  */
  348.  
  349. int
  350. LfsFileBlockAddr(filePtr, blockNum, blocksizePtr)
  351.     LfsFile    *filePtr;    /* File to compute block address of. */
  352.     int        blockNum;    /* Block number we would like the address of. */
  353.     int        *blocksizePtr;    /* OUT: Size in bytes of block blockNum. */
  354. {
  355.     int blockAddr;
  356.     Boolean error;
  357.  
  358.     error = AccessFileBlockAddr(OP_GET, filePtr, blockNum, 
  359.             &blockAddr, blocksizePtr);
  360.     if (error) {
  361.     panic("LfsFileBlockAddr: block error.\n");
  362.     }
  363.     return blockAddr;
  364. }
  365.  
  366. /*
  367.  *----------------------------------------------------------------------
  368.  *
  369.  * LfsFileSetBlockAddr --
  370.  *
  371.  *    Set the address of a file block.
  372.  *
  373.  * Results:
  374.  *    Address of block. FSDM_NIL_INDEX;
  375.  *
  376.  * Side effects:
  377.  *    None.
  378.  *
  379.  *----------------------------------------------------------------------
  380.  */
  381.  
  382. int
  383. LfsFileSetBlockAddr(filePtr, blockNum, blockAddr)
  384.     LfsFile    *filePtr;    /* File to compute block address of. */
  385.     int        blockNum;    /* Block number we would like the address of. */
  386.     int        blockAddr;    /* New block address. */
  387. {
  388.     Boolean error;
  389.     int blocksize;
  390.  
  391.     error = AccessFileBlockAddr(OP_SET, filePtr, blockNum, 
  392.             &blockAddr, &blocksize);
  393.     if (error) {
  394.     panic("LfsFileBlockAddr: block error.\n");
  395.     }
  396.     return blockAddr;
  397. }
  398.  
  399. /*
  400.  *----------------------------------------------------------------------
  401.  *
  402.  * AccessFileBlockAddr --
  403.  *
  404.  *    Set or Get the address of a file block.
  405.  *
  406.  * Results:
  407.  *    TRUE if we found an error.
  408.  *
  409.  * Side effects:
  410.  *    None.
  411.  *
  412.  *----------------------------------------------------------------------
  413.  */
  414.  
  415. static Boolean
  416. AccessFileBlockAddr(op, filePtr, blockNum, blockaddrPtr, blocksizePtr)
  417.     enum AccessFileOp op;    /* OP_GET or OP_SET. */
  418.     LfsFile    *filePtr;    /* File to compute block address of. */
  419.     int        blockNum;    /* Block number we would like the address of. */
  420.     int        *blockaddrPtr;    /* OUT: Addresss of blockNum. */
  421.     int        *blocksizePtr;    /* OUT: Size in bytes of block blockNum. */
  422. {
  423.     LfsFileBlock    *indirBlockPtr;
  424.     int        *blockPtrs;
  425.     int        parentBlockNum, parentIndex;
  426.     LfsFileDescriptor *descPtr;
  427.     ReturnStatus status;
  428.  
  429.     (*blocksizePtr) = FS_BLOCK_SIZE;
  430.     descPtr = LfsFileFetchDesc(filePtr);
  431.     if (blockNum >= 0) { 
  432.     int    fileSize;
  433.     /*
  434.      * Block is a data block. 
  435.      */
  436.     fileSize = descPtr->common.lastByte+1;
  437.     if (blockNum * FS_BLOCK_SIZE > fileSize) {
  438.         /*
  439.          * Block is passed the end of the file.
  440.          */
  441.         if (op == OP_GET) {
  442.         (*blockaddrPtr) =  FSDM_NIL_INDEX;
  443.         return FALSE;
  444.         } else {
  445.         return TRUE;
  446.         }
  447.     } 
  448.     if (blockNum * FS_BLOCK_SIZE > fileSize - FS_BLOCK_SIZE) {
  449.         /*
  450.          * Block might be less than FS_BLOCK_SIZE because the next block
  451.          * is passed the end of the file.
  452.          */
  453.         (*blocksizePtr) = fileSize - blockNum * FS_BLOCK_SIZE;
  454.     }
  455.     if (blockNum < FSDM_NUM_DIRECT_BLOCKS) {
  456.         if (op == OP_GET) {
  457.         (*blockaddrPtr) = descPtr->common.direct[blockNum];
  458.         } else {
  459.         descPtr->common.direct[blockNum] = (*blockaddrPtr);
  460.         LfsFileStoreDesc(filePtr);
  461.         }
  462.         return FALSE;
  463.     }
  464.     if (blockNum < (FSDM_NUM_DIRECT_BLOCKS + FSDM_INDICES_PER_BLOCK)) {
  465.         /*
  466.          * Block address pointer is in the first indirect block.
  467.          */
  468.         parentBlockNum = -1;
  469.         parentIndex = blockNum - FSDM_NUM_DIRECT_BLOCKS;
  470.         status = LfsFileBlockFetch(filePtr, parentBlockNum, &indirBlockPtr);
  471.         if (status != SUCCESS) {
  472.         return TRUE;
  473.         }
  474.         blockPtrs = (int *) LfsFileBlockMem(indirBlockPtr);
  475.         if (op == OP_GET) {
  476.         (*blockaddrPtr) = blockPtrs[parentIndex];
  477.         } else {
  478.         blockPtrs[parentIndex] = (*blockaddrPtr);
  479.         LfsFileStoreBlock(indirBlockPtr, -1);
  480.         }
  481.         return FALSE;
  482.     }
  483.     if (blockNum < (FSDM_NUM_DIRECT_BLOCKS + FSDM_INDICES_PER_BLOCK +
  484.                FSDM_INDICES_PER_BLOCK*FSDM_INDICES_PER_BLOCK)) {
  485.         /*
  486.          * Block address pointer is in a second level indirect block.
  487.          */
  488.         parentBlockNum = -((FSDM_NUM_INDIRECT_BLOCKS+1) +
  489.           (blockNum - FSDM_NUM_DIRECT_BLOCKS - FSDM_INDICES_PER_BLOCK)/
  490.             FSDM_INDICES_PER_BLOCK);
  491.         parentIndex = (blockNum - FSDM_NUM_DIRECT_BLOCKS - 
  492.                FSDM_INDICES_PER_BLOCK) % FSDM_INDICES_PER_BLOCK;
  493.  
  494.         status = LfsFileBlockFetch(filePtr, parentBlockNum, &indirBlockPtr);
  495.         if (status != SUCCESS) {
  496.         return TRUE;
  497.         }
  498.         blockPtrs = (int *) LfsFileBlockMem(indirBlockPtr);
  499.         if (op == OP_GET) {
  500.         (*blockaddrPtr) = blockPtrs[parentIndex];
  501.         } else {
  502.         blockPtrs[parentIndex] = (*blockaddrPtr);
  503.         LfsFileStoreBlock(indirBlockPtr, -1);
  504.         }
  505.         return FALSE;
  506.     }
  507.     } else {
  508.     /*
  509.      * Block is an indirect block.
  510.      */
  511.     if (blockNum >= -FSDM_NUM_INDIRECT_BLOCKS) { 
  512.         /*
  513.          * This is a direct indirect block.
  514.          */
  515.         if (op == OP_GET) {
  516.         (*blockaddrPtr) = descPtr->common.indirect[(-blockNum)-1];
  517.         } else {
  518.         descPtr->common.indirect[(-blockNum)-1] = (*blockaddrPtr);
  519.         LfsFileStoreDesc(filePtr);
  520.         }
  521.         return FALSE;
  522.     }
  523.     if (blockNum > -(FSDM_NUM_INDIRECT_BLOCKS + FSDM_INDICES_PER_BLOCK)) {
  524.         parentIndex = (-blockNum) - (FSDM_NUM_INDIRECT_BLOCKS+1);
  525.         parentBlockNum = -2;
  526.         status = LfsFileBlockFetch(filePtr, parentBlockNum, &indirBlockPtr);
  527.         if (status != SUCCESS) {
  528.         return TRUE;
  529.         }
  530.         blockPtrs = (int *) LfsFileBlockMem(indirBlockPtr);
  531.         if (op == OP_GET) {
  532.         (*blockaddrPtr) = blockPtrs[parentIndex];
  533.         } else {
  534.         blockPtrs[parentIndex] = (*blockaddrPtr);
  535.         LfsFileStoreBlock(indirBlockPtr, -1);
  536.         }
  537.         return FALSE;
  538.     }
  539.     }
  540.     /*
  541.      * Past the largest file size that we support.
  542.      */
  543.    return(TRUE);
  544.  
  545. }
  546.  
  547.  
  548. /*
  549.  *----------------------------------------------------------------------
  550.  *
  551.  * LfsFileStoreDesc --
  552.  *
  553.  *    Mark the file to write back changes to the descriptor.
  554.  *
  555.  * Results:
  556.  *    SUCCESS
  557.  *
  558.  * Side effects:
  559.  *    None.
  560.  *
  561.  *----------------------------------------------------------------------
  562.  */
  563. ReturnStatus
  564. LfsFileStoreDesc(filePtr)
  565.     LfsFile    *filePtr;    /* File for each descriptor was changed. */
  566. {
  567.     filePtr->descModified = TRUE;
  568.     return SUCCESS;
  569. }
  570.  
  571. /*
  572.  *----------------------------------------------------------------------
  573.  *
  574.  * LfsFileStoreBlock --
  575.  *
  576.  *    Mark the file block as dirty and to write back changes.
  577.  *
  578.  * Results:
  579.  *    SUCCESS
  580.  *
  581.  * Side effects:
  582.  *    None.
  583.  *
  584.  *----------------------------------------------------------------------
  585.  */
  586. ReturnStatus
  587. LfsFileStoreBlock(fileBlockPtr, newSize)
  588.     LfsFileBlock *fileBlockPtr;    /* Block block that was changed. */
  589.     int    newSize;
  590. {
  591.     fileBlockPtr->modified = TRUE;
  592.     if (newSize >= 0) {
  593.     fileBlockPtr->blockSize = newSize;
  594.     }
  595.     return SUCCESS;
  596. }
  597.  
  598. ReturnStatus 
  599. LfsFileNameLookup(dirFilePtr, name, fileNumberPtr, dirOffsetPtr)
  600.     LfsFile *dirFilePtr;
  601.     char *name;
  602.     int *fileNumberPtr;
  603.     int *dirOffsetPtr;
  604. {
  605.     int    blockNum, length,  blockOffset;
  606.     ReturnStatus    status;
  607.     LfsFileDescriptor    *descPtr;
  608.     Fslcl_DirEntry *newEntryPtr;
  609.     LfsFileBlock    *dirBlockPtr;
  610.     int     dirOffset, compLen, blockSize;
  611.     char    *blockPtr;
  612.  
  613.     descPtr = LfsFileFetchDesc(dirFilePtr);
  614.     if (descPtr->common.fileType != FS_DIRECTORY) {
  615.     return FS_NOT_DIRECTORY;
  616.     }
  617.     length = descPtr->common.lastByte+1;
  618.     if ((length % FSLCL_DIR_BLOCK_SIZE) != 0) {
  619.     panic("Directory %d has bad length %d\n", descPtr->fileNumber, length);
  620.     return FAILURE;
  621.     }
  622.     /*
  623.      * Find an available slot. 
  624.      */
  625.     dirOffset = -1;
  626.     compLen = strlen(name);
  627.     for (blockNum = 0; blockNum*FS_BLOCK_SIZE < length; blockNum++) {
  628.     status = LfsFileBlockFetch(dirFilePtr, blockNum, &dirBlockPtr);
  629.     if (status != SUCCESS) {
  630.         return FS_FILE_NOT_FOUND;
  631.     }
  632.     blockOffset = 0;
  633.     blockSize = LfsFileBlockSize(dirBlockPtr);
  634.     blockPtr = LfsFileBlockMem(dirBlockPtr);
  635.     while (blockOffset < blockSize) {
  636.         newEntryPtr = (Fslcl_DirEntry *) (blockPtr + blockOffset);
  637.         if ((newEntryPtr->fileNumber != 0) &&
  638.             (newEntryPtr->nameLength == compLen) &&
  639.         (strcmp(newEntryPtr->fileName, name) == 0)) {
  640.             (*fileNumberPtr) = newEntryPtr->fileNumber;
  641.             (*dirOffsetPtr) = blockNum * FS_BLOCK_SIZE + blockOffset;
  642.             return SUCCESS;
  643.         }
  644.         blockOffset += newEntryPtr->recordLength;
  645.         }
  646.     }
  647.     return FS_FILE_NOT_FOUND;
  648. }
  649.  
  650.  
  651.  
  652. static LfsFile    *
  653. GetDirtyFile(lfsPtr)
  654.     Lfs    *lfsPtr;    /* File system to return dirty file from. */
  655. {
  656.     LfsFile    *filePtr;
  657.  
  658.     if (List_IsEmpty(&lfsPtr->fileLayout.activeFileListHdr)) {
  659.     return (LfsFile *) NIL;
  660.     }
  661.     filePtr = (LfsFile *) List_First(&lfsPtr->fileLayout.activeFileListHdr);
  662.     List_Remove((List_Links *) filePtr);
  663.     filePtr->beingWritten = TRUE;
  664.  
  665.     return filePtr;
  666. }
  667.  
  668.  
  669. static void
  670. ReturnDirtyFile(filePtr, onFront)
  671.     LfsFile    *filePtr;    /* File to return. */
  672.     Boolean    onFront;    /* Of front of list. */
  673. {
  674.     Lfs    *lfsPtr = filePtr->lfsPtr;
  675.  
  676.     if (!List_IsEmpty(&filePtr->blockListHdr) || filePtr->descModified) {
  677.     if (onFront) {
  678.         List_Insert((List_Links *) filePtr, 
  679.         LIST_ATFRONT(&lfsPtr->fileLayout.activeFileListHdr));
  680.     } else {
  681.         List_Insert((List_Links *) filePtr, 
  682.         LIST_ATREAR(&lfsPtr->fileLayout.activeFileListHdr));
  683.     }
  684.     filePtr->beingWritten = FALSE;
  685.     return;
  686.     }
  687.  
  688.     free((char *) filePtr);
  689.     return;
  690. }
  691.  
  692. static 
  693. LfsFileBlock *
  694. GetDirtyBlock(filePtr, blockType, lastDirtyBlockPtr)
  695.     LfsFile *filePtr;    /* File to get dirty block of. */
  696.     int blockType;    /* Type of block wanted. */
  697.     int *lastDirtyBlockPtr; /* OUT: TRUE if this is the last dirty block. */
  698. {
  699.     LfsFileBlock    *fileBlockPtr;
  700.     int            blockNum;
  701.  
  702.     LIST_FORALL(&filePtr->blockListHdr, (List_Links *) fileBlockPtr) {
  703.     blockNum = fileBlockPtr->blockNum;
  704.     if (((blockType == LFS_FILE_LAYOUT_DATA) && (blockNum < 0)) ||
  705.         ((blockType == LFS_FILE_LAYOUT_INDIRECT) && 
  706.                   ((blockNum >= 0) || (blockNum == -2))) || 
  707.         ((blockType == LFS_FILE_LAYOUT_DBL_INDIRECT) && (blockNum != -2))) { 
  708.         continue;
  709.     } 
  710.     if (!fileBlockPtr->modified) {    
  711.         panic("Non-modified block on list in GetDirtyBlock");
  712.     }
  713.     List_Remove((List_Links *) fileBlockPtr);
  714.     (*lastDirtyBlockPtr) = List_IsEmpty(&filePtr->blockListHdr);
  715.     return fileBlockPtr;
  716.     }
  717.  
  718.     return (LfsFileBlock *) NIL;
  719.  
  720. }
  721.  
  722. static void
  723. ReturnDirtyBlock(fileBlockPtr, written)
  724.     LfsFileBlock *fileBlockPtr;
  725.     Boolean    written;
  726. {
  727.     if (written) {
  728.     free((char *) fileBlockPtr);
  729.     return;
  730.     }
  731.     fileBlockPtr->modified = TRUE;
  732.     List_Insert((List_Links *) fileBlockPtr, 
  733.         LIST_ATFRONT(&fileBlockPtr->filePtr->blockListHdr));
  734. }
  735.  
  736.  
  737. typedef struct FileSegLayout {
  738.     int     numDescSlotsLeft;    /* Number of slots left in descriptor block. */
  739.     LfsFileDescriptor *descBlockPtr;        
  740.                 /* Pointer to next slot in descriptor block. */
  741.     int         descDiskAddr;     /* Disk address of descriptor block. */
  742.     int maxElements;          /* The maximum number of elements. */
  743.     List_Links    fileList; /* List of files in this segment. */
  744.     List_Links  blockList; /* List of cache blocks laidout in
  745.                        * this segment.  */
  746.     LfsFile    *activeFilePtr;    /* File current being written. */
  747. } FileSegLayout;
  748.  
  749. static Boolean PlaceFileInSegment _ARGS_((LfsSeg *segPtr, 
  750.     LfsFile *filePtr,  FileSegLayout *segLayoutDataPtr));
  751.  
  752.     static FileSegLayout  *segLayoutDataPtr = (FileSegLayout *) NIL;
  753.  
  754.  
  755. /*
  756.  *----------------------------------------------------------------------
  757.  *
  758.  * LfsFileLayoutCheckpoint --
  759.  *
  760.  *    Routine to handle checkpointing of the file layout data.
  761.  *
  762.  * Results:
  763.  *    TRUE if more data needs to be written, FALSE if this module is
  764.  *    checkpointed.
  765.  *
  766.  * Side effects:
  767.  *    Many
  768.  *
  769.  *----------------------------------------------------------------------
  770.  */
  771. /*ARGSUSED*/
  772. Boolean
  773. LfsFileLayoutCheckpoint(segPtr, checkPointPtr,  checkPointSizePtr)
  774.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  775.     char   *checkPointPtr;      /* Buffer to write checkpoint data. */
  776.     int       *checkPointSizePtr;  /* Bytes added to the checkpoint area.*/
  777. {
  778.     Lfs            *lfsPtr =   segPtr->lfsPtr;
  779.     Boolean        full;
  780.     LfsFile        *filePtr;
  781.  
  782.      /*
  783.       * Next spill the file with dirty blocks into the segment. 
  784.       */
  785.      full = FALSE;
  786.      if (segLayoutDataPtr == (FileSegLayout *) NIL) {
  787.  
  788.     /*
  789.      * Allocate a FileSegLayout data structure for this segment. 
  790.      */
  791.      segLayoutDataPtr = (FileSegLayout *) malloc(sizeof(FileSegLayout));
  792.      segLayoutDataPtr->numDescSlotsLeft = 0;
  793.      List_Init(&segLayoutDataPtr->fileList);
  794.      List_Init(&segLayoutDataPtr->blockList);
  795.      segLayoutDataPtr->maxElements = LfsSegSizeInBlocks(lfsPtr);
  796.      segLayoutDataPtr->activeFilePtr = (LfsFile *) NIL;
  797.      } 
  798.      /*
  799.       * Choose the first file. If the last call to layout data into this
  800.       * segment ended with a partially layed out file, start with that file.
  801.       */
  802.      if (segLayoutDataPtr->activeFilePtr == (LfsFile *) NIL) { 
  803.       filePtr = GetDirtyFile(lfsPtr);
  804.       lfsPtr->pstats.fileWritten++;
  805.      } else {
  806.       filePtr = segLayoutDataPtr->activeFilePtr;
  807.      }
  808.      while (!full && (filePtr != (LfsFile *) NIL)) {
  809.        full = PlaceFileInSegment(segPtr, filePtr, segLayoutDataPtr);
  810.        if (full) {
  811.            segLayoutDataPtr->activeFilePtr = filePtr;
  812.            break;
  813.        } 
  814.        List_Insert((List_Links *) filePtr, 
  815.                 LIST_ATREAR(&segLayoutDataPtr->fileList));
  816.        filePtr = GetDirtyFile(lfsPtr);
  817.     }
  818.     if (!full && List_IsEmpty(&segLayoutDataPtr->fileList)) {
  819.     free((char *)segLayoutDataPtr);
  820.     segLayoutDataPtr = (FileSegLayout *) NIL;
  821.     }
  822.     return full;
  823.  
  824. }
  825.  
  826.  
  827. /*
  828.  *----------------------------------------------------------------------
  829.  *
  830.  * PlaceFileInSegment --
  831.  *
  832.  *    Place specified file dirty in segment.
  833.  *
  834.  * Results:
  835.  *    TRUE if the segment filled before the file was fully added.
  836.  *
  837.  * Side effects:
  838.  *    None.
  839.  *
  840.  *----------------------------------------------------------------------
  841.  */
  842. static Boolean 
  843. PlaceFileInSegment(segPtr, filePtr, segLayoutDataPtr)
  844.     LfsSeg    *segPtr;    /* Segment to place data. */
  845.     LfsFile     *filePtr;    /* File to place in segment. */
  846.     FileSegLayout  *segLayoutDataPtr; /* Current layout data for segment. */
  847. {
  848.     Lfs        *lfsPtr = segPtr->lfsPtr;
  849.     LfsFileLayoutSummary *fileSumPtr;
  850.     Boolean    full;
  851.     LfsSegElement    *bufferPtr;
  852.     char    *summaryPtr;
  853.     int        lfsBlocksPerBlock, lastDirtyBlock;
  854.     int        blockType, oldAddr;
  855.     int        blocksNeeded, bytesNeeded, blocksLeft;
  856.     ReturnStatus    status;
  857.     LfsFileBlock        *firstBlockPtr;
  858.     LfsFileBlock        *blockPtr;
  859.  
  860.     if (filePtr == (LfsFile *) NIL) {
  861.     return FALSE;
  862.     }
  863.     /*
  864.      * Layout the blocks of the file into the segment starting with the
  865.      * data blocks.
  866.      */
  867.     full = FALSE;
  868.     fileSumPtr = (LfsFileLayoutSummary *) NIL;
  869.     lfsBlocksPerBlock = LfsBytesToBlocks(lfsPtr, FS_BLOCK_SIZE);
  870.     for (blockType = LFS_FILE_LAYOUT_DATA; 
  871.     (blockType <= LFS_FILE_LAYOUT_DBL_INDIRECT) && !full;  blockType++) { 
  872.     /*
  873.      * Do all of one blockType first before going to the next.
  874.      * Try to checkout just enought blocks that will fit in this
  875.      * segment. We prefetch the first block so that we know if
  876.      * we have zero blocks to layout and don't have to add a
  877.      * LfsFileLayoutSummary.
  878.      */
  879.     firstBlockPtr = GetDirtyBlock(filePtr,  blockType,
  880.                  &lastDirtyBlock);
  881.     /*
  882.      * No more blocks of this type available for this file, go on to 
  883.      * the next blockType. 
  884.      */ 
  885.     if (firstBlockPtr == (LfsFileBlock *) NIL) {
  886.         continue;
  887.     }
  888.        /*
  889.         * Allocate the layout summary bytes of this file if 
  890.         * we haven't done so already.
  891.         */
  892.        if (fileSumPtr == (LfsFileLayoutSummary *) NIL) {
  893.        /*
  894.         * Since we haven't done so already, allocate a LfsFileLayoutSummary
  895.         * for this file in summary block.  Besure there is at least 
  896.         * enough space for one block. If the block that we justed got 
  897.         * (ie firstBlockPtr) is the last block in the cache we ensure
  898.         * that there is enough room for it.  Otherwise we require at 
  899.         * least a entire blocks worth.
  900.         */
  901.        blocksNeeded =  (lastDirtyBlock != 0) ? lfsBlocksPerBlock : 
  902.             LfsBytesToBlocks(lfsPtr, LfsFileBlockSize(firstBlockPtr));
  903.        bytesNeeded = sizeof(LfsFileLayoutSummary) + sizeof(int);
  904.        summaryPtr = LfsSegGrowSummary(segPtr, blocksNeeded, bytesNeeded);
  905.        if (summaryPtr == (char *) NIL) { 
  906.            /*
  907.             * No room in summary. Return block and exit loop.
  908.         */
  909.            ReturnDirtyBlock(firstBlockPtr, FALSE);
  910.            full = TRUE;
  911.            break;
  912.        }
  913.        /*
  914.         * Fill in the LfsFileLayoutSummary with the value we 
  915.         * know now.
  916.         */
  917.        fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  918.        fileSumPtr->blockType = LFS_FILE_LAYOUT_DATA;
  919.        fileSumPtr->numDataBlocks = 0;
  920.        fileSumPtr->numBlocks = 0; /* Filled in later. */
  921.        fileSumPtr->fileNumber = filePtr->desc.fileNumber;
  922.        status = LfsDescMapGetVersion(lfsPtr, 
  923.                fileSumPtr->fileNumber, &fileSumPtr->truncVersion);
  924.        if (status != SUCCESS) {
  925.            panic( "Can't get truncate version number\n");
  926.        }
  927.        summaryPtr += sizeof(LfsFileLayoutSummary);
  928.        LfsSegSetSummaryPtr(segPtr, summaryPtr);
  929.        }
  930.        /*
  931.         * Place the blocks in the segment in reverse order so that
  932.         * they will occur on disk in forward order. This is done
  933.     * by looping until we have collected enough blocks to fill the
  934.     * segments or we run out of cache blocks.  Note that we are
  935.     * permitted to overrun the segment because the code below will
  936.     * return the blocks to the cache.
  937.     *
  938.     * The first block we push on the list is the block we prefetched
  939.     * above.
  940.     */
  941.        blocksLeft = LfsSegBlocksLeft(segPtr);
  942.        blockPtr = firstBlockPtr;
  943.        do {  
  944.        List_Insert((List_Links *) blockPtr, 
  945.             LIST_ATFRONT(&segLayoutDataPtr->blockList));
  946.        blocksLeft -= LfsBytesToBlocks(lfsPtr, LfsFileBlockSize(blockPtr));
  947.        if (blocksLeft > 0) {
  948.            blockPtr = GetDirtyBlock(filePtr,  blockType, 
  949.             &lastDirtyBlock);
  950.         }
  951.     } while ((blocksLeft > 0) && (blockPtr != (LfsFileBlock *) NIL));
  952.  
  953.     /*
  954.      * Interate forward thru the blocks we pushed on the list to 
  955.      * lay them out in the reverse order.  We allow the first
  956.      * block to layout to be a fragment, so we start off by
  957.      * computing the number of fs blocks needed by the first
  958.      * cache block.
  959.      */
  960.     blockPtr = (LfsFileBlock *) List_First(&segLayoutDataPtr->blockList);
  961.     blocksNeeded = LfsBytesToBlocks(lfsPtr, LfsFileBlockSize(blockPtr));
  962.  
  963.     LIST_FORALL(&segLayoutDataPtr->blockList, (List_Links *) blockPtr) {
  964.         int bytesUsed;
  965.        /*
  966.         * Make sure there is enough room for both the data blocks in 
  967.         * the data region and the block number in the summary region.
  968.         */
  969.        summaryPtr = LfsSegGrowSummary(segPtr, blocksNeeded, sizeof(int));
  970.        if (summaryPtr == (char *) NIL) {
  971.            full = TRUE;
  972.            break;
  973.        }
  974.        segPtr->lfsPtr->pstats.fileBlockWritten += blocksNeeded;
  975.        /*
  976.         * Yes there is; add the cache block and fill in the summary region.
  977.         * Update the LfsFileLayoutSummary to reflect the data block being
  978.         * added and the number of fs blocks used.
  979.         */
  980.        *(int *) summaryPtr = blockPtr->blockNum;
  981.        summaryPtr += sizeof(int);
  982.        LfsSegSetSummaryPtr(segPtr,summaryPtr);
  983.        bufferPtr = LfsSegAddDataBuffer(segPtr, blocksNeeded, 
  984.                 LfsFileBlockMem(blockPtr), (ClientData) blockPtr);
  985.  
  986.        fileSumPtr->numDataBlocks++; 
  987.        fileSumPtr->numBlocks += blocksNeeded;
  988.  
  989.        /*
  990.         * Update the index for this file and increment the 
  991.         * active bytes of the segment by the size of the cache
  992.         * block rounded to file system blocks.
  993.         */
  994.        bytesUsed = LfsBlocksToBytes(lfsPtr,
  995.             LfsBytesToBlocks(lfsPtr, blockPtr->blockSize));
  996.        oldAddr = LfsFileBlockAddress(blockPtr);
  997.        if (oldAddr != FSDM_NIL_INDEX) {
  998.            LfsSegUsageAdjustBytes(lfsPtr, oldAddr, -bytesUsed);
  999.        }
  1000.        (void) LfsFileSetBlockAddr(filePtr,
  1001.                 blockPtr->blockNum,
  1002.                 LfsSegDiskAddress(segPtr, bufferPtr));
  1003.        segPtr->activeBytes += bytesUsed;
  1004.        /*
  1005.         * Any blocks after the first one must be of FS_BLOCK_SIZE 
  1006.         * size.
  1007.         */
  1008.        blocksNeeded = lfsBlocksPerBlock;
  1009.        /*
  1010.         * Stop going down the list when we get to the first block we
  1011.         * pushed on.
  1012.         */
  1013.        if (blockPtr == firstBlockPtr) {
  1014.         break;
  1015.        }
  1016.     } 
  1017.     if (full) { 
  1018.         while(1) {
  1019.         LfsFileBlock *nextBlockPtr;
  1020.         /*
  1021.          * We're not able to place all the blocks, return to the cache
  1022.          * all blocks we couldn't place.
  1023.          */
  1024.         nextBlockPtr = (LfsFileBlock *) 
  1025.                 List_Next((List_Links *)blockPtr);
  1026.         List_Remove((List_Links *) blockPtr);
  1027.         ReturnDirtyBlock(blockPtr, FALSE);
  1028.         if (blockPtr == firstBlockPtr) {
  1029.             break;
  1030.         }
  1031.         blockPtr = nextBlockPtr;
  1032.         } 
  1033.     }
  1034.     }
  1035.     if (full) { 
  1036.      return full;
  1037.     }
  1038.    /*
  1039.     * If the segment we are adding has no slots open in the descriptor
  1040.     * block try to allocate a new descriptor block.
  1041.     */
  1042.     if (segLayoutDataPtr->numDescSlotsLeft == 0) {
  1043.     LfsFileLayoutDesc    *descSumPtr;
  1044.     int        descBlocks, descBytes;
  1045.  
  1046.     /*
  1047.      * Compute the size and add the descriptor block.
  1048.      */
  1049.     descBytes = lfsPtr->superBlock.fileLayout.descPerBlock * 
  1050.             sizeof(LfsFileDescriptor);
  1051.     descBlocks = LfsBytesToBlocks(lfsPtr, descBytes);
  1052.  
  1053.     summaryPtr = LfsSegGrowSummary(segPtr, descBlocks, 
  1054.                         sizeof(LfsFileLayoutDesc));
  1055.     if (summaryPtr != (char *) NIL) {
  1056.         LfsSegElement *descBufferPtr;
  1057.         char      *descMemPtr;
  1058.         /*
  1059.          * Allocate space for the descriptor block and fill in a
  1060.          * summary block describing it. 
  1061.          */
  1062.         descBufferPtr = LfsSegAddDataBuffer(segPtr, descBlocks,
  1063.                         (char *) NIL, (ClientData) NIL);
  1064.         segLayoutDataPtr->numDescSlotsLeft = lfsPtr->superBlock.fileLayout.descPerBlock;
  1065.         segLayoutDataPtr->descDiskAddr = 
  1066.                 LfsSegDiskAddress(segPtr, descBufferPtr);
  1067.         descMemPtr = malloc(descBytes);
  1068.         segLayoutDataPtr->descBlockPtr = (LfsFileDescriptor *) descMemPtr;
  1069.         descBufferPtr->address = descMemPtr;
  1070.  
  1071.         descSumPtr = (LfsFileLayoutDesc *) summaryPtr;
  1072.  
  1073.         descSumPtr->blockType =  LFS_FILE_LAYOUT_DESC;
  1074.         descSumPtr->numBlocks = descBlocks;
  1075.  
  1076.         summaryPtr += sizeof(LfsFileLayoutDesc);
  1077.         LfsSegSetSummaryPtr(segPtr, summaryPtr);
  1078.  
  1079.     }
  1080.     }
  1081.     /*
  1082.      * If we successfully place this file in the segment add the descriptor
  1083.      * to the descriptor block. If this is no room then mark the segment 
  1084.      * as full.
  1085.      */
  1086.     if (segLayoutDataPtr->numDescSlotsLeft > 0) {
  1087.       LfsFileDescriptor *lfsDescPtr;
  1088.       int        diskAddr;
  1089.       lfsDescPtr = LfsFileFetchDesc(filePtr);
  1090.       lfsDescPtr->common.flags &= ~FSDM_FD_DIRTY;
  1091.       filePtr->descModified = FALSE;
  1092.       bcopy((char *) &(lfsDescPtr->common), 
  1093.         (char *)&(segLayoutDataPtr->descBlockPtr->common),
  1094.         (int)sizeof(lfsDescPtr->common));
  1095.       segLayoutDataPtr->descBlockPtr->fileNumber = filePtr->desc.fileNumber;
  1096.       status = LfsDescMapGetDiskAddr(lfsPtr, 
  1097.             (int)segLayoutDataPtr->descBlockPtr->fileNumber, 
  1098.             &diskAddr);
  1099.       if (diskAddr != FSDM_NIL_INDEX) {
  1100.            LfsSegUsageAdjustBytes(lfsPtr, diskAddr, 
  1101.                 -sizeof(LfsFileDescriptor));
  1102.       }
  1103.       status = LfsDescMapSetDiskAddr(lfsPtr, 
  1104.             (int)segLayoutDataPtr->descBlockPtr->fileNumber, 
  1105.             segLayoutDataPtr->descDiskAddr);
  1106.       if (status != SUCCESS) {
  1107.           panic("Can't update descriptor map.\n");
  1108.       }
  1109.       segLayoutDataPtr->descBlockPtr++;
  1110.       segLayoutDataPtr->numDescSlotsLeft--;
  1111.       segPtr->activeBytes += sizeof(LfsFileDescriptor);
  1112.       segPtr->lfsPtr->pstats.descWritten++;
  1113.      } else {
  1114.      full = TRUE;
  1115.      }
  1116.      return full;
  1117. }
  1118.  
  1119.  
  1120.  
  1121. /*
  1122.  *----------------------------------------------------------------------
  1123.  *
  1124.  * LfsFileLayoutWriteDone --
  1125.  *
  1126.  *    Routine to handle finishing of file layout writes
  1127.  *
  1128.  * Results:
  1129.  *    None
  1130.  *
  1131.  * Side effects:
  1132.  *    Many
  1133.  *
  1134.  *----------------------------------------------------------------------
  1135.  */
  1136. /*ARGSUSED*/
  1137. void
  1138. LfsFileLayoutWriteDone(segPtr, flags)
  1139.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  1140.     int       flags;        /* Flags for checkpoint */
  1141. {
  1142.     LfsSegElement *bufferPtr = LfsSegGetBufferPtr(segPtr);
  1143.     char     *summaryPtr =  LfsSegGetSummaryPtr(segPtr);
  1144.     char     *limitPtr;
  1145.     LfsFileBlock*blockPtr;
  1146.     LfsFile *filePtr;
  1147.  
  1148.     limitPtr = summaryPtr + LfsSegSummaryBytesLeft(segPtr); 
  1149.      while (summaryPtr < limitPtr) { 
  1150.     switch (*(unsigned short *) summaryPtr) {
  1151.     case LFS_FILE_LAYOUT_DESC: {
  1152.          free(bufferPtr->address);
  1153.          bufferPtr++;
  1154.          summaryPtr += sizeof(LfsFileLayoutDesc);
  1155.          break;
  1156.     }
  1157.     case LFS_FILE_LAYOUT_DATA:  {
  1158.         LfsFileLayoutSummary *fileSumPtr;
  1159.         /* 
  1160.          * All these records should be pointing to a cache blocks which
  1161.          * must be released.
  1162.          */
  1163.         fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  1164.         bufferPtr += fileSumPtr->numDataBlocks;
  1165.         summaryPtr += (sizeof(LfsFileLayoutSummary) + 
  1166.                fileSumPtr->numDataBlocks * sizeof(int));
  1167.         break;
  1168.     }
  1169.     case LFS_FILE_LAYOUT_DIR_LOG: {
  1170.         LfsFileLayoutLog    *logSumPtr = (LfsFileLayoutLog *) summaryPtr;
  1171.          /*
  1172.           * Because we copied and truncated the log during layout we 
  1173.           * don't need to do anything on write complete.
  1174.           */
  1175.         summaryPtr = summaryPtr + sizeof(LfsFileLayoutLog);
  1176.         bufferPtr += logSumPtr->numDataBlocks;
  1177.         break;
  1178.     }
  1179.     case LFS_FILE_LAYOUT_DBL_INDIRECT: 
  1180.     case LFS_FILE_LAYOUT_INDIRECT: 
  1181.     default:
  1182.         panic("Bad file block type in summary block");
  1183.     }
  1184.     }
  1185.     LfsSegSetBufferPtr(segPtr, bufferPtr);
  1186.     if (segLayoutDataPtr != (FileSegLayout *) NIL) {
  1187.     while (!List_IsEmpty(&segLayoutDataPtr->blockList)) {
  1188.         blockPtr = (LfsFileBlock *)
  1189.                 List_First(&segLayoutDataPtr->blockList);
  1190.         List_Remove((List_Links *)blockPtr);
  1191.         ReturnDirtyBlock(blockPtr, TRUE);
  1192.     }
  1193.     while (!List_IsEmpty(&segLayoutDataPtr->fileList)) {
  1194.         filePtr = 
  1195.         (LfsFile *) List_First(&segLayoutDataPtr->fileList);
  1196.         List_Remove((List_Links *)filePtr);
  1197.         ReturnDirtyFile(filePtr, TRUE);
  1198.     }
  1199.     if (segLayoutDataPtr->activeFilePtr != (LfsFile *) NIL) {
  1200.         ReturnDirtyFile(segLayoutDataPtr->activeFilePtr, TRUE);
  1201.     }
  1202.     free((char *) segLayoutDataPtr);
  1203.     segLayoutDataPtr = (FileSegLayout *) NIL;
  1204.     }
  1205.     return;
  1206.  
  1207. }
  1208.  
  1209.  
  1210.